﻿using Server.DTool;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Server.Struct
{
    /// <summary>
    /// 保存已使用引用
    ///          emptyIndex
    /// ---已使用---|---未使用---
    /// </summary>
    public class ResPool<Item> where Item : class, IPoolItem
    {
        List<Item> _items;

        int _emptyIndex = 0;

        Func<Item> _creater;
        Action<Item> _beforeRecycle;
        Action<Item> _beforeTake;

        //资源使用超时时间
        long _timeOut;

        public bool HasEmpty => _emptyIndex < _items.Count;

        //List<Item> _used;
        //List<Item> _unused;
        //public virtual List<Item> Used
        //{
        //    get
        //    {
        //        _used.Clear();
        //        for (int i = 0; i < _emptyIndex; i++)
        //            _used.Add(_items[i]);
        //        return _used;
        //    }
        //}
        //public virtual List<Item> Unused
        //{
        //    get
        //    {
        //        _unused.Clear();
        //        for (int i = _emptyIndex; i < _items.Capacity; i++)
        //            _unused.Add(_items[i]);
        //        return _unused;
        //    }
        //}

        public ResPool(int capcity, Func<Item> creater)
        {
            Init(capcity, creater, null, null);
        }

        void Init(int capcity, Func<Item> creater, Action<Item> beforeTake, Action<Item> beforeRecycle)
        {
            _items = new List<Item>(capcity);

            Set(creater, beforeTake, beforeRecycle);

            for (int i = 0; i < capcity; i++)
            {
                Item item = _creater();

                item.ItemId = i;

                item.Index = i;
                _items.Add(item);
            }

            //_used = new List<Item>(capcity);
            //_unused = new List<Item>(capcity);
        }

        public void Set(Func<Item> creater, Action<Item> beforeTake, Action<Item> beforeRecycle)
        {
            _creater = new Func<Item>(creater);
            _beforeTake = beforeTake;
            _beforeRecycle = beforeRecycle;
        }

        public void Set(Action<Item> beforeTake, Action<Item> beforeRecycle)
        {
            _beforeTake = beforeTake;
            _beforeRecycle = beforeRecycle;
        }

        public virtual Item Take()
        {
            if (_emptyIndex >= _items.Capacity)
                throw new ArgumentOutOfRangeException("没有可取对象");

            _beforeTake?.Invoke(_items[_emptyIndex]);
            _items[_emptyIndex].Index = _emptyIndex;

            return _items[_emptyIndex++];
        }

        public virtual void Recycle(Item t)
        {
            _Recycle(t);
        }

        void _Recycle(Item t)
        {
            _beforeRecycle?.Invoke(t);

            _emptyIndex--;

            int index = t.Index;

            CommolOption.Switch<Item, List<Item>>(_items, index, _emptyIndex);

            t.Index = _emptyIndex;
            _items[index].Index = index;
        }

        public virtual void RecycleAll(Func<Item, bool> conditdion)
        {
            for (int i = _emptyIndex - 1; i >= 0; i--)
            {
                if (conditdion.Invoke(_items[i]))
                {
                    Console.WriteLine("RecycleAll");
                    _Recycle(_items[i]);
                }
            }
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder(string.Format("EmptyIndex:{0}\n", _emptyIndex));
            foreach (var item in _items)
            {
                sb.AppendFormat("[{0}]:{1} ", item.Index, item);
            }
            sb.AppendLine();
            return sb.ToString();
        }

        //public struct PoolEnumerator<T> : IEnumerator<T>
        //{
        //    List<T> _list;
        //    int _offset;
        //    int _count;

        //    int _index;
        //    T _current;

        //    public T Current
        //    {
        //        get
        //        {
        //            return _current;
        //        }
        //    }

        //    object IEnumerator.Current
        //    {
        //        get
        //        {
        //            return _current;
        //        }
        //    }

        //    internal PoolEnumerator(List<T> list, int offset, int count)
        //    {
        //        _list = list;
        //        _offset = offset;
        //        _count = count;
        //        _index = offset;
        //        _current = default;
        //    }

        //    public void Dispose()
        //    {

        //    }

        //    public bool MoveNext()
        //    {
        //        if (_index < _offset + _count)
        //        {
        //            _current = _list[_index];
        //            _index++;
        //            return true;
        //        }
        //        return false;
        //    }

        //    public void Reset()
        //    {
        //        _index = _offset;
        //        _current = default;
        //    }
        //}
    }
}
